//TileForwardNormalMapInstFX.h
//Created 23/10/13
//Created By Daniel Bowler
//
//Similar to the TileForwardNormalMapFX, but with added support for
//hardware instancing. Used when you want to render the same (normal mapped)
//geometry multiple times (Draw calls are VERY expensive. I5 2500k at stock
//will be CPU bound after 250 odd draw calls (With a z pre pass stage too))
//
//******NON-UNIFORM SCALING IS BANNED - MESSES UP THE TBN MATRIX*******

#pragma once

#include "AbstractFX.h"

class TileForwardNormalMapInstFX : public AbstractFX
{
	//Ensure that the ShaderManager can access private functions - the constructor/
	//destructor. Thus, the ShaderManager will be the only class allowed to 
	//create/destroy Effects.
	friend ShaderManager;
public:
	//Per vertex structure.
	struct PerVertexData
	{
		XMFLOAT3 PosL;
		XMFLOAT3 NormalL;
		XMFLOAT2 Tex;
		XMFLOAT3 TangentL;
	};
	//Per instance structure (HI = Hardware Instancing)
	struct PerInstancedData
	{
		XMFLOAT4X4 WorldM;
	};

	//Set render target dimension data
	void SetRTDimensions(unsigned width, unsigned height);
	
	//Set Light List Buffer (Global lights buffer - Shader Manager can call this)
	void SetLightListBuffer(ID3D11ShaderResourceView* lightListBuffer);

	//Sets cbuffer data
	void SetCBufferPerDrawCall(CXMMATRIX& viewProj, CXMMATRIX& texTrans, Material& mat, 
		CXMMATRIX& view);

	//Set Texture Data
	void SetShaderResources(ID3D11ShaderResourceView* diffuseMap,
		ID3D11ShaderResourceView* normalMap);

	//Set lighting data.
	void SetLightingData(XMFLOAT3& eye, DirectionalLight* dLights, unsigned dLightCount, 
		ID3D11ShaderResourceView* lightListIndexBuffer, 
		ID3D11ShaderResourceView* lightListStartEndBuffer);
	
	//Sets hemispherical ambient colour data
	void SetHemisphericalData(XMFLOAT3 &hemiColDown, XMFLOAT3 &hemiColRange);

	//Set SSAO Map and transform data
	void SetSSAOData(ID3D11ShaderResourceView* ssaoTex, CXMMATRIX &transform);
	
	//Sets the environment map - Note Material::Reflection determins how
	//much of the enviromnet is reflected on the model. Very shiny models
	//should have more reflectivity and mat models less. Also, flat models
	//should NOT have any reflectivity because the effect looks shit. 
	void SetEnvironmentMap(ID3D11ShaderResourceView* envCubeMap);
	
	//Sets shadow map
	void SetShadowMap(ID3D11ShaderResourceView* shadowMap);
	void SetShadowMapMatricies(CXMMATRIX &view, CXMMATRIX &proj, CXMMATRIX &toTex);

private:
	TileForwardNormalMapInstFX(ID3D11Device* device);
	~TileForwardNormalMapInstFX();
	//Disable copy constrcutor and assignment operator
	TileForwardNormalMapInstFX(TileForwardNormalMapInstFX& copy);
	TileForwardNormalMapInstFX& operator=(TileForwardNormalMapInstFX& other);

	//Override the init methods.
	void InitInputLayout(ID3D11Device* device);
	void InitShaderVariablePointers();

private:
	//Variables.
	//
	//Cbuffer Data:
	ID3DX11EffectMatrixVariable* viewProjVar;
	ID3DX11EffectMatrixVariable* texTransformVar;

	//Render dimensions
	ID3DX11EffectScalarVariable* rtWidthVar;
	ID3DX11EffectScalarVariable* rtHeightVar;

	//Texture Data:
	ID3DX11EffectShaderResourceVariable* diffuseMapVar;
	ID3DX11EffectShaderResourceVariable* normalMapVar;  

	//Lighting data
	ID3DX11EffectVectorVariable* eyePosVar;
	ID3DX11EffectVariable* materialVar;
	//Direc Lights
	ID3DX11EffectVariable* direcLightVar;
	ID3DX11EffectScalarVariable* direcLightCountVar;
	//Point/Spot lights - Tile Forward System
	ID3DX11EffectShaderResourceVariable* llbVar;
	ID3DX11EffectShaderResourceVariable* llibVar;
	ID3DX11EffectShaderResourceVariable* llsebVar;

	//Hemispheric Ambient lighting colours
	ID3DX11EffectVectorVariable* hemiColDownVar;
	ID3DX11EffectVectorVariable* hemiColRangeVar;
	
	//SSAO
	ID3DX11EffectMatrixVariable* viewVar;
	ID3DX11EffectShaderResourceVariable* ssaoMapVar;
	ID3DX11EffectMatrixVariable* ssaoWorldViewProjTexVar;

	//Environment map
	ID3DX11EffectShaderResourceVariable* envMapVar;
	
	//Shadow Map
	ID3DX11EffectShaderResourceVariable* shadowMapVar;
	ID3DX11EffectMatrixVariable* shadowMapViewVar;
	ID3DX11EffectMatrixVariable* shadowMapProjVar;
	ID3DX11EffectMatrixVariable* shadowMapToTexVar;
};